﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Text.RegularExpressions;
using AdaptationProject.Forms;
using AdaptationProject.Properties;



namespace AdaptationProject.Utils
{
    class Ckeck
    {
        public static bool CheckValidValue(string str,
                                           string regExValue,
                                           string fullName,
                                           Control ctrl,
                                           ErrorProvider errorProviderInput,
                                           ToolStripStatusLabel toolStripStatusLabel)
        {
            Regex regex = new Regex(regExValue);
            if (!regex.IsMatch(str) && str != "")
            {
                errorProviderInput.SetError(ctrl, "Введите пожалуйста " + fullName);
                toolStripStatusLabel.Text = "Поле должно содержать только " + fullName;
                return false;

            }
            else
            {
                errorProviderInput.SetError(ctrl, "");
                toolStripStatusLabel.Text = "";
                return true;
            }
        }
    }

    /// <summary>
    /// Парсер параметра по типу
    /// </summary>
    public class ParamParser
    {
        private float floatDiff = 0.5f;
        private int rounding = 2;
        public IList<object> Parse(string values, int type)
        {
            IList<object> valuesList = new List<object>();
            switch (type)
            {
                case ParamType.STRING:
                case ParamType.FILENAME:
                    valuesList.Add((object)values);
                    break;

                case ParamType.INT:
                case ParamType.FLOAT:
                    valuesList = GetListOfAcceptableValues(values, type);
                    break;

                case ParamType.SYMBOL:
                    valuesList = GetListOfAcceptableValues(values, type);
                    break;

                case ParamType.FILE:
                case ParamType.HELPFILE:
                    valuesList.Add((object)values);
                    break;

                case ParamType.HANDLE:
                    valuesList.Add((object)values);
                    break;

                case ParamType.PATH:
                    valuesList.Add((object)values);
                    break;

                case ParamType.UNKNOWN:
                default:
                    MessageBox.Show("Выбран неверный тип параметра!\nПовторите еще раз",
                                    "Ошибка в выборе типа параметра",
                                    MessageBoxButtons.OK,
                                    MessageBoxIcon.Error);
                    break;
            }
            
            return valuesList;
        }

        /// <summary>
        /// Возвращает преобразованные параметры
        /// </summary>
        /// <param name="rangedValues">Значение параметра.</param>
        /// <param name="type">Тип параметра.</param>
        private IList<object> GetListOfAcceptableValues(string rangedValues, int type)
        {
            if (string.IsNullOrEmpty(rangedValues))
            {
                throw new ArgumentNullException(Resources.XMLParser_Range_Is_Empty);
            }

            // разбор по типу
            IList<object> toRet = new List<object>();
            try
            {
                string[] values = rangedValues.Split(';');
                foreach (string value in values)
                {
                    if (value.Contains('~'))
                    {
                        switch (type)
                        {
                            case ParamType.INT:
                                AddIntRange(value, ref toRet);
                                break;

                            case ParamType.FLOAT:
                                AddFloatRange(value, ref toRet);
                                break;

                            case ParamType.SYMBOL:
                                AddSymbolRange(value, ref toRet);
                                break;
                        }
                    }
                    else
                    {
                        if (value.Length == 0)
                            continue;

                        switch (type)
                        {
                            case ParamType.INT:
                                {
                                    long boundary;
                                    Int64.TryParse(value, out boundary);
                                    toRet.Add(boundary);
                                }
                                break;

                            case ParamType.FLOAT:
                                {
                                    float boundary;
                                    string replcaedValue = value.Replace('.', ',');
                                    float.TryParse(replcaedValue, out boundary);
                                    toRet.Add(boundary);
                                }
                                break;

                            case ParamType.SYMBOL:
                                {
                                    toRet.Add(value);
                                }
                                break;
                        }
                    }
                }
            }
            catch (Exception e)
            {
                ParamName paramName = new ParamName();

                MessageBox.Show("Неверный тип параметра: " + rangedValues +
                                " \'" + paramName.typeName[type] + "\'" + "\n" + e.Message);
                toRet.Add("");
                return toRet;
            }
            
            return toRet;
        }

        /// <summary>
        /// Заполняет список значений параметра при обнаружении 
        /// интервала числовых значений.
        /// </summary>
        /// <param name="value">Интервальное значение.</param>
        /// <param name="listValues">Список допустимых состояний.</param>
        private void AddIntRange(string value, ref IList<object> listValues)
        {
            long leftBoundary, rightBoundary;
            string[] boundaryValues = value.Split('~');
            if (!Int64.TryParse(boundaryValues[0], out leftBoundary) ||
                !Int64.TryParse(boundaryValues[1], out rightBoundary))
            {
                throw new Exception(Resources.XMLParser_Range_Values_Must_Be_Digits);
            }
            if (leftBoundary > rightBoundary)
            {
                long tmp      = rightBoundary;
                rightBoundary = leftBoundary;
                leftBoundary  = tmp;
            }

            for (long i = leftBoundary; i <= rightBoundary; ++i)
            {
                listValues.Add(i);
            }
        }

        // <summary>
        /// Заполняет список значений параметра при обнаружении 
        /// интервала числовых значений.
        /// </summary>
        /// <param name="value">Интервальное значение.</param>
        /// <param name="listValues">Список допустимых состояний.</param>
        private void AddFloatRange(string value, ref IList<object> listValues)
        {
            float leftBoundary, rightBoundary;
            value = value.Replace('.', ',');

            string[] boundaryValues = value.Split('~');
            if (!float.TryParse(boundaryValues[0], out leftBoundary) ||
                !float.TryParse(boundaryValues[1], out rightBoundary))
            {
                throw new Exception(Resources.XMLParser_Range_Values_Must_Be_Digits);
            }
            if (leftBoundary > rightBoundary)
            {
                float tmp     = rightBoundary;
                rightBoundary = leftBoundary;
                leftBoundary  = tmp;
            }

            for (float i = leftBoundary; i <= rightBoundary; i += floatDiff)
            {
                listValues.Add(Math.Round(i, rounding));
            }
        }

        // <summary>
        /// Заполняет список значений параметра при обнаружении 
        /// интервала числовых значений.
        /// </summary>
        /// <param name="value">Интервальное значение.</param>
        /// <param name="listValues">Список допустимых состояний.</param>
        private void AddSymbolRange(string value, ref IList<object> listValues)
        {
            char leftBoundary, rightBoundary;
            string[] boundaryValues = value.Split('~');
            if (!char.TryParse(boundaryValues[0], out leftBoundary) ||
                !char.TryParse(boundaryValues[1], out rightBoundary))
            {
                throw new Exception(Resources.XMLParser_Range_Values_Must_Be_Digits);
            }
            if (leftBoundary > rightBoundary)
            {
                char tmp      = rightBoundary;
                rightBoundary = leftBoundary;
                leftBoundary  = tmp;
            }

            for (char i = leftBoundary; i <= rightBoundary; ++i)
            {
                listValues.Add(i);
            }
        }
    }
}
